{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;}
\margl40
\margr40
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i0\ulnone\fs24\fc0\cf0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//
\i 	
\b FILENAME
\b0 :	
\b\i0 eTLinkWell.m \

\b0 //
\i 	
\b SUMMARY
\b0 :	
\b\i0 Defines a well for drag-and-drop of .etfLink files.
\b0 \
//	
\b\i SUPERCLASS
\b0 :
\i0 	
\b Object:Resonder:View:Control:Button:eTLinkWell
\b0 \
//	
\b\i PROTOCOLS
\b0 :
\i0 	
\b None
\b0 \
//	
\b\i INTERFACE
\b0 :
\i0 	
\b None. Instantiate as a customView in IB.
\b0 \
//	
\b\i AUTHOR
\b0 :		
\b\i0 Rohit Khare
\b0 \
//	
\b\i COPYRIGHT
\b0 :	
\f1\i0 с
\f0\b 1993,94 California Institure of Technology, eText Project\

\b0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b\i Implementation Comments
\b0\i0 \
//		This as gross a hack as they come. There, I said it. Ok?\
//	This is a true perversion of target-action... but it works.\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b\i HISTORY
\b0\i0 \
//	10/04/94:	
\b Revamped for eText5
\b0 \
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b Imported Interfaces
\b0 \
//\
	#import "
\b eTLinkWell.h
\b0 "\
\

\i @implementation eTLinkWell\

\i0 // 
\b\i Dragging URL-Squiggle support!//	For those fine guys at OmniGroup :)
\b0\i0 \
- 
\b initOmniWell
\b0 \
\{\
	[self 
\b registerForDraggedTypes
\b0 :&
\b NXAsciiPboardType
\b0  count:1];\
	[self setEnabled:NO];\
	[self setType:NX_PUSHONPUSHOFF];\
	[self setBordered:NO];\
	[self 
\b setIcon
\b0 :
\b EMPTY
\b0 ];\
	[self 
\b setAltIcon
\b0 : 
\b LIT
\b0 ];\
	[self 
\b setTitle
\b0 :"
\b Drag an OmniWeb URL here:
\b0 "];\
	[self 
\b setIconPosition
\b0 :
\b NX_ICONRIGHT
\b0 ];\
	
\b omniMode
\b0  = 
\b YES
\b0 ;\
	return self;\
\}\
- 
\b initLinkWell
\b0 \
\{\
	const char *fileType[] = \{
\b NXFilenamePboardType
\b0 , 
\b NXFileContentsPboardType
\b0 \};\
	[self 
\b registerForDraggedTypes
\b0 :fileType count:2];\
	
\b currentLink.docID
\b0  = 
\b NULL
\b0 ;\
	[self setEnabled:NO];\
	[self setIconPosition:NX_ICONONLY];\
	[self setType:NX_PUSHONPUSHOFF];\
	[self setBordered:NO];\
	[self 
\b setIcon
\b0 :
\b EMPTY
\b0 ];\
	[self 
\b setAltIcon
\b0 : 
\b LIT
\b0 ];\
	
\b omniMode
\b0  = 
\b NO
\b0 ;\
	return self;\
\}\
\
- 
\b setLink
\b0 :(etfLink *)
\b theLink
\b0 \
\{	\
	if (
\b theLink
\b0  == 
\b NULL
\b0 ) \{\
		// 
\i clear out to the default image
\i0 \
		[self 
\b setIcon
\b0 :
\b EMPTY
\b0 ];\
		
\b currentLink.docID
\b0  = 
\b NULL
\b0 ;\
	\} else \{\
		// 
\i display "occupied" image
\i0 \
		[self 
\b setIcon
\b0 :
\b FULL
\b0 ];\
		
\b currentLink
\b0  = *
\b theLink
\b0 ;\
	\}\
	return self;\
\}\
\
- (etfLink *) 
\b currentLink 
\b0 \{
\b return
\b0  
\b &currentLink
\b0 ;\}\
\
- (NXDragOperation) 
\b draggingEntered
\b0 :sender\
\{\
	NXAtom 	types[3];\
	id		thePB;\
\
	if (
\b !
\b0 [[self 
\b target
\b0 ] 
\b respondsTo
\b0 :[self 
\b action
\b0 ]]) return 
\b NX_DragOperationNone
\b0 ;\
	if ([sender 
\b draggingSource
\b0 ] == 
\b self
\b0 ) return 
\b NX_DragOperationNone
\b0 ;\
	if (
\b omniMode
\b0 ) \{\
		return 
\b NX_DragOperationGeneric
\b0 ;\
	\}\
	thePB = [sender draggingPasteboard];\
	types[0] = NXFilenamePboardType;\
	types[1] = 
\b NXCreateFileContentsPboardType
\b0 (
\b LINK_EXT
\b0 );\
	types[2] = NULL;\
	types[2] = [thePB 
\b findAvailableTypeFrom
\b0 :types num:2];\
	if (
\b !types
\b0 [2]) \{\
		return 
\b NX_DragOperationNone
\b0 ;\
	\} else if (types[2] == types[0]) \{\
		char	*data;\
		int		len,i=0,j=0;\
		BOOL	found=NO;\
		\
		[thePB 
\b readType
\b0 :
\b NXFilenamePboardType
\b0  data:&
\b data
\b0  length:&len];\
		while ((j < len) && !found)\{\
			i = j;\
			while (data[i] && (data[i] != '\\t')) i++;\
			data[i] = 0;\
			if (!
\b strcmp
\b0 (
\b LINK_EXT
\b0 , rindex(
\b data
\b0 +j, '.')+1)) 
\b found
\b0  = 
\b YES
\b0 ;\
			else if (!
\b strcmp
\b0 (
\b ETFD_EXT
\b0 , rindex(
\b data
\b0 +j, '.')+1)) 
\b found
\b0  = 
\b YES
\b0 ;\
			j = i+1;\
		\}\
		[thePB 
\b deallocatePasteboardData
\b0 :data length:len];\
		if (
\b !found
\b0 ) return 
\b NX_DragOperationNone
\b0 ;\
	\}\
	[self 
\b setState
\b0 :
\b 1
\b0 ];\
	return 
\b NX_DragOperationLink
\b0 ;\
\}\
- 
\b draggingExited
\b0 :sender \{return [self 
\b setState
\b0 :
\b 0
\b0 ];\}\
- (BOOL)
\b prepareForDragOperation
\b0 :sender \{return 
\b YES
\b0 ;\}\
- (BOOL)
\b performDragOperation
\b0 :sender\
\{\
	id theTable;\
	NXAtom 	types[3];\
	id		thePB;\
	BOOL	found=NO;\
\
	thePB = [sender draggingPasteboard];\
	if (
\b omniMode
\b0 ) \{\
		[omniText 
\b setSel
\b0 :
\b 0
\b0 :[omniText 
\b textLength
\b0 ]];\
		[omniText 
\b readSelectionFromPasteboard
\b0 :
\b thePB
\b0 ];\
		[[self 
\b target
\b0 ] 
\b perform
\b0 :[self 
\b action
\b0 ] 
\b with
\b0 :
\b self
\b0 ];\
		return 
\b YES
\b0 ;\
	\}\
	types[0] = NXFilenamePboardType;\
	types[1] = NXCreateFileContentsPboardType(
\b LINK_EXT
\b0 );\
	types[2] = [thePB findAvailableTypeFrom:types num:2];\
\
	if (
\b !types
\b0 [2]) return 
\b NO
\b0 ;\
	else if (types[2] == types[0]) \{\
		char	*data;\
		int		len,i=0,j=0;\
		\
		[thePB 
\b readType
\b0 :
\b NXFilenamePboardType
\b0  data:&
\b data
\b0  length:&len];\
		while ((j < len) && !found)\{\
			i = j;\
			while (data[i] && (data[i] != '\\t')) i++;\
			data[i] = 0;\
			theTable = nil;\
			if (!
\b strcmp
\b0 (
\b LINK_EXT
\b0 , rindex(
\b data
\b0 +j, '.')+1))\{\
				// 
\i read this file in and issue the accept...:
\i0 \
				
\b theTable
\b0  = [[
\b NXStringTable
\b0  alloc] 
\b init
\b0 ];\
				[theTable 
\b readFromFile
\b0 :data+j];\
			\} else if (!
\b strcmp
\b0 (
\b ETFD_EXT
\b0 , rindex(
\b data
\b0 +j, '.')+1)) \{\
				// 
\i find a docID for this file, stash it away\

\i0 				
\b theTable
\b0 =[[[
\b eTDocInfo
\b0  alloc] 
\b init
\b0 ] 
\b readComponentFromPath
\b0 :data+j];\
			\}\
			if (
\b theTable
\b0 ) \{\
				currentLink.
\b docID
\b0  = \
					NXUniqueString([theTable valueForStringKey:
\b DOCID
\b0 ]);\
				currentLink.
\b anchorID
\b0  = \
					NXUniqueString([theTable valueForStringKey:
\b ANCHORID
\b0 ]);\
				currentLink.
\b docTitle
\b0  = \
					NXUniqueString([theTable valueForStringKey:
\b DOCTITLE
\b0 ]);\
				currentLink.
\b anchorTitle
\b0  =\
				NXUniqueString([theTable valueForStringKey:
\b ANCHORTITLE
\b0 ]);\
				if (currentLink.
\b anchorID
\b0  == 
\b NULL
\b0 )\
					currentLink.anchorID = NXUniqueString("
\b 0
\b0 ");\
				if (currentLink.
\b anchorTitle
\b0  == 
\b NULL
\b0 )\
					currentLink.anchorTitle = NXUniqueString("
\b Untitled
\b0 ");\
				[[self 
\b target
\b0 ] 
\b perform
\b0 :[self 
\b action
\b0 ] 
\b with
\b0 :
\b self
\b0 ];\
				found = 
\b YES
\b0 ;\
				if (!
\b strcmp
\b0 (
\b LINK_EXT
\b0 , 
\b rindex
\b0 (data+j, '.')+1))\{\
					theTable = [[
\b theTable
\b0  
\b empty
\b0 ]
\b  free
\b0 ];\
					if (!
\b strncmp
\b0 (
\b data
\b0 +j, "
\b /tmp
\b0 ", 
\b 4
\b0 ) 
\b &&
\b0  \
					   ((
\b rindex
\b0 (
\b data
\b0 +j, '
\b /
\b0 ')-(
\b data
\b0 +j)) == 
\b 5
\b0 )) \
					   
\b unlink
\b0 (
\b data
\b0 +j);\
				\}\
			\}\
			j = i+1;\
		\}\
		[thePB 
\b deallocatePasteboardData
\b0 :data length:len];\
	\} else if (types[2] == types[1]) \{\
		sprintf(path, "
\b /tmp/%d.etfLink
\b0 ", [NXApp 
\b uniqueID
\b0 ]);\
		free([thePB 
\b readFileContentsType
\b0 :\
			NXCreateFileContentsPboardType(
\b LINK_EXT
\b0 ) 
\b toFile
\b0 :
\b path
\b0 ]);\
		// 
\i "... returns an allocated string..."\

\i0 		// 
\i read this file in and issue the accept...:
\i0 \
		
\b theTable
\b0  = [[
\b NXStringTable
\b0  alloc] 
\b init
\b0 ];\
		if ([theTable 
\b readFromFile
\b0 :
\b path
\b0 ]) \{\
			currentLink.
\b docID
\b0  = \
				NXUniqueString([theTable valueForStringKey:
\b DOCID
\b0 ]);\
			currentLink.
\b anchorID
\b0  = \
				NXUniqueString([theTable valueForStringKey:
\b ANCHORID
\b0 ]);\
			currentLink.
\b docTitle
\b0  = \
				NXUniqueString([theTable valueForStringKey:
\b DOCTITLE
\b0 ]);\
			currentLink.
\b anchorTitle
\b0  =\
				NXUniqueString([theTable valueForStringKey:
\b ANCHORTITLE
\b0 ]);\
			if (currentLink.
\b anchorID
\b0  == 
\b NULL
\b0 )\
				currentLink.anchorID = NXUniqueString("
\b 0
\b0 ");\
			if (currentLink.
\b anchorTitle
\b0  == 
\b NULL
\b0 )\
				currentLink.anchorTitle = NXUniqueString("
\b Untitled
\b0 ");\
			[[self 
\b target
\b0 ] 
\b perform
\b0 :[self 
\b action
\b0 ] 
\b with
\b0 :
\b self
\b0 ];\
			found = 
\b YES
\b0 ;\
		\}\
		theTable = [[
\b theTable
\b0  
\b empty
\b0 ] 
\b free
\b0 ];\
		
\b unlink
\b0 (
\b path
\b0 );\
	\}\
	[self 
\b setState
\b0 :
\b 0
\b0 ];\
	return found;\
\}\
\
- (NXDragOperation)
\b draggingSourceOperationMaskForLocal
\b0 :(BOOL)
\b isLocal
\b0 \
\{\
	return (
\b isLocal
\b0  ? 
\b NX_DragOperationLink
\b0  : 
\b NX_DragOperationAll
\b0 );\
\}\
- (BOOL)
\b acceptsFirstMouse
\b0  \{return 
\b YES
\b0 ;\}\
- (BOOL)
\b shouldDelayWindowOrderingForEvent
\b0 :(NXEvent *)
\b e
\b0 \
\{\
	return (
\b currentLink.docID
\b0  ? YES : NO);\
\}\
- 
\b mouseDown
\b0 :(NXEvent *)
\b e
\b0 \
\{\
	id		theTable;\
	NXPoint	org;\
	NXPoint offset;\
	id		dragPasteboard;\
	NXAtom	types[3];\
	\
	if (
\b currentLink.docID
\b0  == 
\b NULL
\b0 ) 
\b return
\b0  self;\
	
\b theTable
\b0  = [[
\b NXStringTable
\b0  alloc] 
\b init
\b0 ];\
	[theTable 
\b insertKey
\b0 :
\b DOCID
\b0  value:NXCopyStringBuffer(currentLink.
\b docID
\b0 )];\
	[theTable insertKey:
\b ANCHORID
\b0  value:NXCopyStringBuffer(currentLink.
\b anchorID
\b0 )];\
	[theTable insertKey:
\b DOCTITLE
\b0  value:NXCopyStringBuffer(currentLink.
\b docTitle
\b0 )];\
	[theTable insertKey:
\b ANCHORTITLE
\b0  value: NXCopyStringBuffer(currentLink.
\b anchorTitle
\b0 )];\
	sprintf(
\b path
\b0 , "
\b /tmp/%s.etfLink
\b0 ", currentLink.
\b anchorTitle
\b0 );\
	[theTable 
\b writeToFile
\b0 :
\b path
\b0 ];\
	theTable = [[
\b theTable empty
\b0 ] 
\b free
\b0 ];\
\
	
\b dragPasteboard
\b0  = [Pasteboard newName: 
\b NXDragPboard
\b0 ];\
	types[0] = NXFilenamePboardType;\
	types[1] = NXFileContentsPboardType;\
	types[2] = NULL;\
	[dragPasteboard 
\b declareTypes
\b0 :types num:2 owner:nil];\
	[dragPasteboard 
\b writeType
\b0 :types[0] data:
\b path
\b0  length:strlen(path)+1];\
	[dragPasteboard 
\b writeFileContents
\b0 :
\b path
\b0 ];\
	\
	org = e->location;\
	[self 
\b convertPoint
\b0 :&
\b org
\b0  
\b fromView
\b0 :
\b nil
\b0 ];\
	org.x -= 5.0; org.y += 5.0;\
	offset.x = offset.y = 0.0;\
	[self 
\b dragImage
\b0 :[NXImage findImageNamed:"
\b NXLinkButton
\b0 "]\
		
\b at
\b0 :&org 
\b offset
\b0 :&offset\
		
\b event
\b0 :e 
\b pasteboard
\b0 :dragPasteboard\
		
\b source
\b0 :self 
\b slideBack
\b0 : YES];		\
	return self;\
\}\
\
- 
\b draggedImage
\b0 :(NXImage *)image 
\b endedAt
\b0 :(NXPoint *)screenPoint 
\b deposited
\b0 :(BOOL)didDeposit\
\{\
// 
\i FIX THIS -- It litters /tmp with junk.\

\i0 //	
\i unlink(path);\

\i0 	return self;\
\}\
@end
}
